//
//  EzHlsMemoryLive.hpp
//  FFTEST_HLS
//
//  Created by 刘跃龙 on 9/30/18.
//  Copyright © 2018 absolutemobile. All rights reserved.
//

#ifndef EzHlsMemoryLive_hpp
#define EzHlsMemoryLive_hpp

#include "EzTools.h"
#include <string>
#include <functional>
#include <list>

#include "linux_lock.h"

#define EZ_HLS_LIVE_MAX_DURATION 3
#define EZ_HLS_LIVE_MIN_DURATION 1
#define EZ_HLS_LIVE_FILE_COUNT 4
#define EZ_HLS_LIVE_FILE_SHOW 2
#define EZ_HLS_LIVE_FILE_HIDE 2

#define TS_FEC_PACKET_SIZE 204
#define TS_DVHS_PACKET_SIZE 192
#define TS_PACKET_SIZE 188
#define TS_MAX_PACKET_SIZE 204

#define NB_PID_MAX 8192
#define MAX_SECTION_SIZE 4096

/* pids */
#define PAT_PID                 0x0000
#define SDT_PID                 0x0011

/* table ids */
#define PAT_TID   0x00
#define PMT_TID   0x02
#define M4OD_TID  0x05
#define SDT_TID   0x42

#define STREAM_TYPE_VIDEO_MPEG1     0x01
#define STREAM_TYPE_VIDEO_MPEG2     0x02
#define STREAM_TYPE_AUDIO_MPEG1     0x03
#define STREAM_TYPE_AUDIO_MPEG2     0x04
#define STREAM_TYPE_PRIVATE_SECTION 0x05
#define STREAM_TYPE_PRIVATE_DATA    0x06
#define STREAM_TYPE_AUDIO_AAC       0x0f
#define STREAM_TYPE_AUDIO_AAC_LATM  0x11
#define STREAM_TYPE_VIDEO_MPEG4     0x10
#define STREAM_TYPE_METADATA        0x15
#define STREAM_TYPE_VIDEO_H264      0x1b
#define STREAM_TYPE_VIDEO_HEVC      0x24
#define STREAM_TYPE_VIDEO_CAVS      0x42
#define STREAM_TYPE_VIDEO_VC1       0xea
#define STREAM_TYPE_VIDEO_DIRAC     0xd1

#define STREAM_TYPE_AUDIO_AC3       0x81
#define STREAM_TYPE_AUDIO_DTS       0x82
#define STREAM_TYPE_AUDIO_TRUEHD    0x83
#define STREAM_TYPE_AUDIO_EAC3      0x87

#define Ez_HLS_UNIT_START 1
#define Ez_HLS_NOT_UNIT_START 0

#define Ez_HLS_ONLY_PAYLOAD 1
#define Ez_HLS_ONLY_ADAPTATION 2
#define Ez_HLS_ADAPTATION_PAYLOAD 3

EZ_BEGIN

class EzHlsMemoryLive
{
public:
    typedef struct HLSItem_t
    {
        int index;
        std::string duration;
        std::string fileName;
//        std::string data;
        char*       pData;
        uint32_t    uDataSize;
        HLSItem_t(){
            index = -1;
            duration = "";
            fileName = "";
            pData = NULL;
            uDataSize = 0;
        }
    }HLSItem;
public:
    EzHlsMemoryLive();
    ~EzHlsMemoryLive();
public:
    void setMediaInfo(uint32_t videoFrequency,uint32_t audioFrequency)
    {
        m_videoFrequency = videoFrequency;
        m_audioFrequency = audioFrequency;
    };
    void cleanData();
    void videoData(uint32_t timestmap,std::string &data);
    void audioData(uint32_t timestmap,std::string &data);
private://TOOLS
    std::string getTsHeader(uint8_t payload_unit_start_indicator,uint16_t pid,uint8_t adaptation_field_control);// 4 Byte
    uint8_t getAdaptationFieldFlag(uint8_t discontinuity_indicator
                                   ,uint8_t random_access_indicator
                                   ,uint8_t elementary_stream_priority_indicator
                                   ,uint8_t PCR_flag
                                   ,uint8_t OPCR_flag
                                   ,uint8_t splicing_point_flag
                                   ,uint8_t transport_private_data_flag
                                   ,uint8_t adaptation_field_extension_flag
                                   );
    std::string getPCR(uint32_t timestmap,uint32_t frequency);
    std::string getPTS(uint32_t timestmap,uint32_t frequency);
    std::string getDTS(uint32_t timestmap,uint32_t frequency);
    std::string getATDS(std::string dsi,size_t packetLen);
    int getCountinuityCounter(int pid);
private://FILE
    std::string m_tsCache;
    LinuxLock m_Cache_mtx;//
    void createNewTs();
    void updateItem(float duration);
    void writePacket(std::string packet);
private://Adaptation
    std::string getTsAdaptationField_stuffing(size_t size);
    std::string getTsAdaptationField_start(size_t stuffingSize = 0);//2 Byte + stuffingSize
    std::string getTsAdaptationField_start_PCR(uint32_t timestmap,uint32_t frequency,size_t stuffingSize = 0);//8 Byte + stuffingSize
private://PES
    void getTsH264PesPacket(uint32_t timestmap,std::string &data);
    void getTsAACPesPacket(uint32_t timestmap,std::string &data);
private://SDT
    std::string getTsPacket_SDT();//188 Byte
    std::string getTsDescriptor_SDT();
    std::string getSection_SDT();
private://PAT
    std::string getTsPacket_PAT();//188 Byte
    std::string getSection_PAT();
private://PMT
    std::string getTsPacket_PMT();//188 Byte
    std::string getSection_PMT();
public://HTTP
    LinuxLock m_item_mtx;//    std::mutex m_item_mtx;
    void getChcheFile(int cameraId,std::string filename,std::string token,std::string &res);
    std::string getHttpRes404();
    std::string getHttpRes200(std::string data);
public:
    uint32_t timestmapCorrecting(uint32_t timestmap);
public:
    int getFileNumber(){return m_fileNumber;};
private:
    int64_t m_lastTimesmtmap;
    int64_t m_offsetTime;
    uint32_t m_startTime;//录制开始的视频秒数(用于列表计算文件时长)
    int m_fileNumber;//文件标号
    int m_maxDuration;//最大秒数
    std::list<EzHlsMemoryLive::HLSItem*> m_itemList;//文件列表
//    std::string testList;
private:
    std::string m_provider_name;
    std::string m_service_name;
    uint16_t m_pmt_pid;
    uint16_t m_program_number;
    uint16_t m_h264_pid;
    uint16_t m_acc_pid;
    uint32_t m_videoFrequency;
    uint32_t m_audioFrequency;
    uint64_t m_systemClockFrequency;
};

EZ_END

#endif /* EzHlsMemoryLive_hpp */
